package encryption;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 一、MD5
 * <p>
 * MD5本质是一种散列函数，用以提供消息的完整性保护。
 * <p>
 * 特点：
 * <p>
 * 1.压缩性：任意长度的数据，算出的MD5值长度都是固定的；
 * <p>
 * 2.容易计算：从原数据计算出MD5值很容易；
 * <p>
 * 3.抗修改性：对原数据进行任何改动，哪怕只修改1个字节，所得到的MD5值都有很大的区别；
 * <p>
 * 4.强抗碰撞：已知原数据和其MD5值，想找到一个具有相同MD5值的数据（及伪造数据）是非常困难的；
 * <p>
 * 5.不可逆：MD5理论上是不可逆的（但是现在已经可以暴力破解了）。
 * <p>
 * 使用场景：
 * <p>
 * 1.验证密码：只要算法不变，就能和服务器上的MD5匹配；
 * <p>
 * 2.文件完整性的校验：当下载一个文件时，服务器返回的信息包括这个文件的md5,在本地下载完毕时进行md5加密，将两个md5值进行比较，如果一致则说明文件完整没有丢包现象。
 * ————————————————
 * 版权声明：本文为CSDN博主「一拳SuperMan」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。
 * 原文链接：https://blog.csdn.net/u011897782/article/details/81163387
 */
//MD5加密
public class MD5Utils {

    //    加密字符串
    public String getMD5Code(String info) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            md5.update(info.getBytes("utf-8"));
            byte[] encryption = md5.digest();
            StringBuffer stringBuffer = new StringBuffer();
            for (int i = 0; i < encryption.length; i++) {
                if (Integer.toHexString(0xff & encryption[i]).length() == 1) {
                    stringBuffer.append("0").append(Integer.toHexString(0xff & encryption[i]));
                } else {
                    stringBuffer.append(Integer.toHexString(0xff & encryption[i]));
                }
            }
            return stringBuffer.toString();
        } catch (Exception e) {
//            e.printStackTrace();
            return "";
        }
    }

    //加密文件
    public static String md5ForFile(File file) {
        int buffersize = 1024;
        FileInputStream fis = null;
        DigestInputStream dis = null;

        try {
            //创建MD5转换器和文件流
            MessageDigest messageDigest = MessageDigest.getInstance("MD5");
            fis = new FileInputStream(file);
            dis = new DigestInputStream(fis, messageDigest);

            byte[] buffer = new byte[buffersize];
            //DigestInputStream实际上在流处理文件时就在内部就进行了一定的处理
            while (dis.read(buffer) > 0) ;

            //通过DigestInputStream对象得到一个最终的MessageDigest对象。
            messageDigest = dis.getMessageDigest();

            // 通过messageDigest拿到结果，也是字节数组，包含16个元素
            byte[] array = messageDigest.digest();
            // 同样，把字节数组转换成字符串
            StringBuilder hex = new StringBuilder(array.length * 2);
            for (byte b : array) {
                if ((b & 0xFF) < 0x10) {
                    hex.append("0");
                }
                hex.append(Integer.toHexString(b & 0xFF));
            }
            return hex.toString();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

}
//————————————————
//        版权声明：本文为CSDN博主「一拳SuperMan」的原创文章，遵循 CC 4.0 BY-SA 版权协议，转载请附上原文出处链接及本声明。
//        原文链接：https://blog.csdn.net/u011897782/article/details/81163387